﻿///////////////////////////////////////////////////////////////
//                                                           //
// Code from Arcanea Project.                                //
//                                                           //
// Please include this license part to every reproduction    //
//   of code.                                                //
//                                                           //
// This code is under Ms-RL license                          //
//                                                           //
// Please read futher information about the license,         //
//   the project (news and updates) and the                  //
//   contributors on the address :                           //
//     http://www.codeplex.com/Arcanea/                      //
//                                                           //
///////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Reflection;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using log4net;

namespace Arcanea.NetworkEngine.Abstract.Engines
{
    /// <summary>
    /// Contrat que doit respecter l'engine de protocole.
    /// La classe qui en hérite ne doit peut etre pas implémenter toutes ces fonctions :
    /// Par exemple un Serveur TCP utilise bing alors qu'un client TCP non.
    /// </summary>
    public abstract class IProtocoleEngine
    {
        protected NetInformationContainer netInformations = new NetInformationContainer();

        protected static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// Etablit la connection
        /// </summary>
        /// <returns></returns>
        public abstract bool Connect();

        /// <summary>
        /// Associe le socket a un point (adresse et port) et commence l'écoute.
        /// En attente de connection
        /// </summary>
        /// <returns></returns>
        public abstract bool Bind();

        /// <summary>
        /// Accepte une connection et retourne un objet identifiant cette connection.
        /// </summary>
        /// <returns>un NetInformationContainer, contenant toutes les infos de la connection fraichement récupéré</returns>
        public abstract NetInformationContainer AcceptedConnection();

        /// <summary>
        /// Envoit un tableur de byte au point distant
        /// </summary>
        /// <param name="array">Tableau à envoyer</param>
        /// <returns>True si tout s'est bien passé</returns>
        public abstract bool Send(byte[] array);

        /// <summary>
        /// Recoit un tableau de donnée de taille fixe.
        /// </summary>
        /// <param name="taille">Taille du tableur à recevoir</param>
        /// <returns>Tableau recu</returns>
        public abstract byte[] Receive(int taille);

        /// <summary>
        /// Ferme la connection courante
        /// </summary>
        /// <returns>True si la connection a bien été fermée sinon false</returns>
        public bool Close()
        {
            try
            {
                if (netInformations.Socket != null)
                {
                    if (netInformations.Socket.Connected)
                    {
                        netInformations.Socket.Shutdown(SocketShutdown.Both);
                    }
                    netInformations.Socket.Close(1000);
                }
                else
                {
                    return false;
                }

                return true;
            }
            catch (Exception e)
            {
                logger.Error(e.ToString());
                return false;
            }
        }
    }
}
